<!DOCTYPE html>
<html lang="zh-cn">
  <head>
    
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1,minimum-scale=1,maximum-scale=1">


<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />



  <meta name="description" content="virtual DOM如何与数据结合？ 如何将virtual DOM反转回DOM？"/>




  <meta name="keywords" content="Vue," />





  <link rel="alternate" href="/default" title="刘粉丝来了">






<link rel="canonical" href="http://yoursite.com/2020/04/10/inversion/"/>


<meta name="description" content="本章为数据响应式化的前置知识点   数据驱动数据驱动：通过控制数据的变化来改变某事某物。 在Vue中就是数据改变视图更新。 主要是通过 Object.defineProperty进行实现下次另写一篇来进行说明。   本篇文章我们约定用 (()) 代替双括号   123456789&lt;p&gt;&amp;#123;&amp;#123; name &amp;#125;&amp;#125;&lt;&#x2F;p&gt;    &#x2F;&#x2F; 刘栓蛋">
<meta property="og:type" content="article">
<meta property="og:title" content="virtual DOM如何与数据结合？ 如何将virtual DOM反转回DOM？">
<meta property="og:url" content="http://yoursite.com/2020/04/10/inversion/index.html">
<meta property="og:site_name" content="刘粉丝来了">
<meta property="og:description" content="本章为数据响应式化的前置知识点   数据驱动数据驱动：通过控制数据的变化来改变某事某物。 在Vue中就是数据改变视图更新。 主要是通过 Object.defineProperty进行实现下次另写一篇来进行说明。   本篇文章我们约定用 (()) 代替双括号   123456789&lt;p&gt;&amp;#123;&amp;#123; name &amp;#125;&amp;#125;&lt;&#x2F;p&gt;    &#x2F;&#x2F; 刘栓蛋">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="http://120.79.197.3:8006/api/image/547e223ed7611644ddbf37f605050298.png">
<meta property="og:image" content="http://120.79.197.3:8006/api/image/d1ad8e361c3dfb2592a86d31d95ac800.png">
<meta property="og:image" content="http://120.79.197.3:8006/api/image/e29e982a99ffe6d04160fa9e90465a49.png">
<meta property="article:published_time" content="2020-04-10T15:57:38.000Z">
<meta property="article:modified_time" content="2020-04-11T10:23:45.988Z">
<meta property="article:author" content="刘粉丝来了">
<meta property="article:tag" content="Vue">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="http://120.79.197.3:8006/api/image/547e223ed7611644ddbf37f605050298.png">


<link rel="stylesheet" type="text/css" href="/css/style.css?v=1.1" />
<link href='https://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet'>





<script type="text/javascript">
  var themeConfig = {
    fancybox: {
      enable: false
    },
  };
</script>




  



    <title> virtual DOM如何与数据结合？ 如何将virtual DOM反转回DOM？ - 刘粉丝来了 </title>
  <meta name="generator" content="Hexo 4.2.0"></head>

  <body>
    <div id="page">
      <header id="masthead"><div class="site-header-inner">
    <h1 class="site-title">
        <a href="/." class="logo">刘粉丝来了</a>
    </h1>

    <nav id="nav-top">
        
            <ul id="menu-top" class="nav-top-items">
                
                    <li class="menu-item">
                        <a href="/">
                            
                            
                                Home
                            
                        </a>
                    </li>
                
                    <li class="menu-item">
                        <a href="/archives">
                            
                            
                                Archives
                            
                        </a>
                    </li>
                
                    <li class="menu-item">
                        <a href="/tags">
                            
                            
                                Tags
                            
                        </a>
                    </li>
                
                    <li class="menu-item">
                        <a href="/about">
                            
                            
                                About
                            
                        </a>
                    </li>
                
            </ul>
        
  </nav>
</div>

      </header>
      <div id="content">
        
    <div id="primary">
        
  <article class="post">
    <header class="post-header">
      <h1 class="post-title">
        
          virtual DOM如何与数据结合？ 如何将virtual DOM反转回DOM？
        
      </h1>

      <time class="post-time">
          4月 10 2020
      </time>
    </header>



    
            <div class="post-content">
            <blockquote>
<p>本章为数据响应式化的前置知识点 </p>
</blockquote>
<h3 id="数据驱动"><a href="#数据驱动" class="headerlink" title="数据驱动"></a><strong>数据驱动</strong></h3><p>数据驱动：通过控制数据的变化来改变某事某物。 在Vue中就是数据改变视图更新。 主要是通过 <code>Object.defineProperty</code>进行实现下次另写一篇来进行说明。</p>
<p><img src="http://120.79.197.3:8006/api/image/547e223ed7611644ddbf37f605050298.png" alt="数据驱动" title="数据驱动"></p>
<blockquote>
<p>本篇文章我们约定用 (()) 代替双括号 </p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&lt;p&gt;&#123;&#123; name &#125;&#125;&lt;<span class="regexp">/p&gt;    /</span><span class="regexp">/ 刘栓蛋</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">export default &#123;</span></span><br><span class="line"><span class="regexp">    data () &#123;</span></span><br><span class="line"><span class="regexp">        return &#123;</span></span><br><span class="line"><span class="regexp">            name:'刘栓蛋'</span></span><br><span class="line"><span class="regexp">        &#125;</span></span><br><span class="line"><span class="regexp">    &#125;</span></span><br><span class="line"><span class="regexp">&#125;</span></span><br></pre></td></tr></table></figure>

<ul>
<li><p>在Vue中我们经常使用<code>双括号</code>表达式进行双向绑定占一个坑位,大家在开发的时候有没有想过为什么这样数据就能进行绑定呢？ 主要是 <code>Object.defineProperty</code>.</p>
</li>
<li><p>new Vue初始化之后挂载组件检测到<code>template</code>时会进行编译，分为三个阶段 <code>parse</code>,<code>optimize</code>,<code>generate</code>,最终得到render function,想了解其中的步骤的请自行百度.</p>
</li>
<li><p>在转换virtual DOM的时候会找到我们埋下的坑就是(( name )), 然后对应的找到data()里面的数据进行替换.</p>
</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line">&lt;div id=<span class="string">"root"</span>&gt;</span><br><span class="line">    &lt;p&gt;&#123;&#123; name &#125;&#125;&lt;<span class="regexp">/p&gt;</span></span><br><span class="line"><span class="regexp">    &lt;p&gt;&#123;&#123; describe &#125;&#125;&lt;/</span>p&gt;</span><br><span class="line">&lt;<span class="regexp">/div&gt;</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">function Vue() &#123;</span></span><br><span class="line"><span class="regexp">    this._template = document.querySelector( options.el );</span></span><br><span class="line"><span class="regexp">    this._data = options.data;</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">    /</span><span class="regexp">/ 接收虚拟DOM</span></span><br><span class="line"><span class="regexp">    this.render =  this.createDOM();</span></span><br><span class="line"><span class="regexp">    </span></span><br><span class="line"><span class="regexp">    /</span><span class="regexp">/ 更新视图</span></span><br><span class="line"><span class="regexp">    this.update(this.render());</span></span><br><span class="line"><span class="regexp">&#125;</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">Vue.prototype.createDOM = function() &#123;</span></span><br><span class="line"><span class="regexp">    /</span><span class="regexp">/ getVNode的实现请查看上一节</span></span><br><span class="line"><span class="regexp">    let virtual = getVNode( this._template );</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">    return function render() &#123;</span></span><br><span class="line"><span class="regexp">        /</span><span class="regexp">/ 找到坑位并替换数据</span></span><br><span class="line"><span class="regexp">        let fabric = combine( virtual, this._data );</span></span><br><span class="line"><span class="regexp">        return fabric;</span></span><br><span class="line"><span class="regexp">    &#125;</span></span><br><span class="line"><span class="regexp">&#125;</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">Vue.prototype.update = function() &#123;</span></span><br><span class="line"><span class="regexp">    /</span><span class="regexp">/ 将虚拟DOM反转回DOM</span></span><br><span class="line"><span class="regexp">    let vray = parseVNode( vnode );</span></span><br><span class="line"><span class="regexp">&#125;</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp"> const app = new Vue(&#123;</span></span><br><span class="line"><span class="regexp">    el:'#root',</span></span><br><span class="line"><span class="regexp">    data:&#123;</span></span><br><span class="line"><span class="regexp">        name:'刘栓蛋',</span></span><br><span class="line"><span class="regexp">        describe:'22岁'</span></span><br><span class="line"><span class="regexp">    &#125;</span></span><br><span class="line"><span class="regexp">&#125;)</span></span><br></pre></td></tr></table></figure>
<p>接下来我们实现 <code>combine</code>以及<code>parseVNode</code>，实现的原理和<code>getVNode</code>大同小异，在递归调用自身后处理类型上有点细微的差别.</p>
<blockquote>
<p>在Vue中 _下划线开头的代表私有属性，在这里我们也用_开头的代表私有属性</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">combine</span>(<span class="params"> node, data </span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> _tag = node.tag;</span><br><span class="line">    <span class="keyword">let</span> _data = node.data;</span><br><span class="line">    <span class="keyword">let</span> _value = node.value;</span><br><span class="line">    <span class="keyword">let</span> _type = node.type;</span><br><span class="line">    <span class="keyword">let</span> children = node.children;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> _vnode = <span class="literal">null</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> ( _type === <span class="number">1</span> ) &#123;</span><br><span class="line">        _vnode = <span class="keyword">new</span> VNode( _tag, _data, _value, _type );</span><br><span class="line">        _vnode.appChildren.forEach(  <span class="function"><span class="params">v</span> =&gt;</span> combine( v, data ) )</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> ( _type === <span class="number">3</span> ) &#123;</span><br><span class="line">        _value = _value.replace(<span class="regexp">/\&#123;\&#123;(.+?)\&#125;\&#125;/g</span>,(_,v) =&gt; &#123;</span><br><span class="line">            <span class="keyword">return</span> data[ v.time() ];</span><br><span class="line">        &#125;)</span><br><span class="line">        _vnode = <span class="keyword">new</span> VNode( _tag, _data, _value, _type );</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> _vnode;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>开始进行分析：</p>
<ul>
<li><p>先看我们传进来的参数 <code>node</code>是转换好的虚拟DOM，<code>data</code>是要替换上去的数据，注意：这个方法就只是替换坑位，只对<code>nodeType</code>为3的文本进行处理，所以如果<code>nodeType</code>为1的情况下，我们就要把虚拟DOM的参数拿出来然后原封不动的还回去.</p>
</li>
<li><p>若<code>nodeType</code>等于3，我们要使用正则匹配双括号,再将里面的内容去空格进行替换.</p>
</li>
</ul>
<p><img src="http://120.79.197.3:8006/api/image/d1ad8e361c3dfb2592a86d31d95ac800.png" alt="坑位" title="坑位替换结果"></p>
<blockquote>
<p>看的累了就先休息下，走马观花不是学习，要理解！！！ </p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 反转虚拟DOM</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">parseVNode</span>(<span class="params"> vnode </span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> type = vnode.type;</span><br><span class="line">    <span class="keyword">let</span> _node = <span class="literal">null</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> ( type === <span class="number">1</span> ) &#123;</span><br><span class="line">        _node = <span class="built_in">document</span>.createElement( vnode.tag );</span><br><span class="line"></span><br><span class="line">        <span class="keyword">let</span> _data = vnode.data;</span><br><span class="line">        <span class="built_in">Object</span>.keys( _data ).forEach( <span class="function"><span class="params">k</span> =&gt;</span> &#123;</span><br><span class="line">            <span class="keyword">let</span> propertyName = k;</span><br><span class="line">            <span class="keyword">let</span> propertyValue = _data[k];</span><br><span class="line">            _node.setAttribute( propertyName, propertyValue );</span><br><span class="line">        &#125;)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">let</span> childNodes = vnode.children;</span><br><span class="line">        <span class="keyword">for</span>( <span class="keyword">let</span> i = <span class="number">0</span>; i &lt; childNodes.length; i++ ) &#123;</span><br><span class="line">            _node.appendChild( parseVNode( childNodes[i] ) )</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> _node;</span><br><span class="line"></span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> ( type === <span class="number">3</span> ) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">document</span>.createTextNode( vnode.value );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>开始分析：</p>
<ul>
<li><p>老样子 <code>nodeType</code>等于1则是元素节点，等于3则是文本节点</p>
</li>
<li><p>等于1的情况下，先利用<code>createElement</code>创建一个元素,紧接着分离出元素的属性，<code>propertyName</code>代表属性名，<code>propertyValue</code>代表属性值，<code>setAttribute</code>方法添加指定的属性，并为其赋指定的值。是不是又看到熟悉的代码片段了，没错 继续递归！</p>
</li>
<li><p>等于3的话，往当前元素追加一个文本节点.</p>
</li>
</ul>
<p><img src="http://120.79.197.3:8006/api/image/e29e982a99ffe6d04160fa9e90465a49.png" alt="反转DOM" title="反转DOM"></p>
<blockquote>
<p>至此 本章完，希望对您有所帮助!</p>
</blockquote>

            </div>
          

    
      <footer class="post-footer">
		
		<div class="post-tags">
		  
			<a href="/tags/Vue/">Vue</a>
		  
		</div>
		

        
        
  <nav class="post-nav">
    
      <a class="prev" href="/2020/04/21/watcher/">
        <i class="iconfont icon-left"></i>
        <span class="prev-text nav-default">依赖收集与派发更新</span>
        <span class="prev-text nav-mobile">上一篇</span>
      </a>
    
    
      <a class="next" href="/2020/04/09/virtual%20DOM/">
        <span class="next-text nav-default">如何将DOM转换为virtual DOM?</span>
        <span class="prev-text nav-mobile">下一篇</span>
        <i class="iconfont icon-right"></i>
      </a>
    
  </nav>

        
  <div class="comments" id="comments">
    
  </div>


      </footer>
    
  </article>


    </div>

      </div>

      <footer id="colophon"><script async src="https://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js">
</script>
<span class="copyright-year" style="width:100%; display:flex; justify-content: space-between;">
    <span>
        
        &copy;
    
        2014 -
    
    2020
    <span class="footer-author">刘粉丝来了.</span>
    <span class="power-by">
        由 <a class="hexo-link" href="https://hexo.io/" target="_blank" rel="noopener">Hexo</a> and <a class="theme-link" href="https://github.com/frostfan/hexo-theme-polarbear" target="_blank" rel="noopener">Polar Bear</a> 强力驱动
    </span>
    </span>
    <span id="busuanzi_container_site_pv">
        本站总访问量<span id="busuanzi_value_site_pv" style="color:red">24280</span>次
    </span>
</span>



      </footer>

      <div class="back-to-top" id="back-to-top">
        <i class="iconfont icon-up"></i>
      </div>
    </div>
    


    




  
    <script type="text/javascript" src="/lib/jquery/jquery-3.1.1.min.js"></script>
  

  

    <script type="text/javascript" src="/js/src/theme.js?v=1.1"></script>
<script type="text/javascript" src="/js/src/bootstrap.js?v=1.1"></script>


  </body>
</html>
